<?php
namespace fast;

use think\facade\Config;
use think\facade\Cache;

class WechatPay
{
    protected $config;
    
    public function __construct()
    {
        $this->config = Config::get('wechat');
    }

    public function getConfig()
    {

        return [
            'appId' => $appId,
            'timestamp' => time(),
            'nonceStr' => $this->generateNonceStr(),
            'signature' => $this->generateSignature(),
        ];
        return $this->config;
    }

    public function generateSignature()
    {
        
    }

    
    /**
     * 获取jsapi_ticket
     * @return string
     */
    public function getJsapiTicket()
    {
        $cacheKey = 'wechat_jsapi_ticket';
        $ticket = Cache::get($cacheKey);
        
        if (!$ticket) {
            $accessToken = $this->getAccessToken();
            $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={$accessToken}&type=jsapi";
            $result = json_decode(file_get_contents($url), true);
            
            if (isset($result['ticket'])) {
                $ticket = $result['ticket'];
                Cache::set($cacheKey, $ticket, 7000); // 缓存7000秒
            }
        }
        
        return $ticket;
    }
    
    /**
     * 获取access_token
     * @return string
     */
    public function getAccessToken()
    {
        $cacheKey = 'wechat_access_token';
        $accessToken = Cache::get($cacheKey);
        
        if (!$accessToken) {
            $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$this->config['app_id']}&secret={$this->config['app_secret']}";
            $result = json_decode(file_get_contents($url), true);
            
            if (isset($result['access_token'])) {
                $accessToken = $result['access_token'];
                Cache::set($cacheKey, $accessToken, 7000); // 缓存7000秒
            }
        }
        
        return $accessToken;
    }
    
    /**
     * 生成支付签名
     * @param array $params
     * @return string
     */
    public function generatePaySign($params)
    {
        ksort($params);
        $string = '';
        foreach ($params as $key => $value) {
            if ($value !== '' && $value !== null) {
                $string .= $key . '=' . $value . '&';
            }
        }
        $string .= 'key=' . $this->config['key'];
        return strtoupper(md5($string));
    }
    
    /**
     * 统一下单
     * @param array $params
     * @return array
     */
    public function unifiedOrder($params)
    {
        $defaultParams = [
            'appid' => $this->config['app_id'],
            'mch_id' => $this->config['mch_id'],
            'nonce_str' => $this->generateNonceStr(),
            'sign_type' => 'MD5',
        ];
        
        $params = array_merge($defaultParams, $params);
        $params['sign'] = $this->generatePaySign($params);
        
        $xml = $this->arrayToXml($params);
        $result = $this->postXmlCurl($xml, 'https://api.mch.weixin.qq.com/pay/unifiedorder');
        
        return $this->xmlToArray($result);
    }
    
    /**
     * 生成支付参数
     * @param string $prepayId
     * @return array
     */
    public function generatePayParams($prepayId)
    {
        $params = [
            'appId' => $this->config['app_id'],
            'timeStamp' => (string)time(),
            'nonceStr' => $this->generateNonceStr(),
            'package' => 'prepay_id=' . $prepayId,
            'signType' => 'MD5'
        ];
        
        $params['paySign'] = $this->generatePaySign($params);
        
        return $params;
    }
    
    /**
     * 生成随机字符串
     * @param int $length
     * @return string
     */
    public function generateNonceStr($length = 16)
    {
        $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        $str = "";
        for ($i = 0; $i < $length; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }
    
    /**
     * 数组转XML
     * @param array $arr
     * @return string
     */
    private function arrayToXml($arr)
    {
        $xml = "<xml>";
        foreach ($arr as $key => $val) {
            if (is_array($val)) {
                $xml .= "<" . $key . ">" . $this->arrayToXml($val) . "</" . $key . ">";
            } else {
                $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
            }
        }
        $xml .= "</xml>";
        return $xml;
    }
    
    /**
     * XML转数组
     * @param string $xml
     * @return array
     */
    public function xmlToArray($xml)
    {
        return json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
    }
    
    /**
     * 发送POST请求
     * @param string $xml
     * @param string $url
     * @param int $second
     * @return string
     */
    private function postXmlCurl($xml, $url, $second = 30)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_TIMEOUT, $second);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_HEADER, false);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
        $data = curl_exec($ch);
        curl_close($ch);
        return $data;
    }
} 